

/**
 * ----------------------------------1.string--------------------------------------
 * 字符串类型
 * */
   let str:string="hello"
   console.log(str);
   str="100"

/**
 * ----------------------------------2.number--------------------------------------
 * number类型
 * */
   let useAge:number;
   useAge=18;

// useAge = true


/**
 * ----------------------------------3.boolean-------------------------------------
 * bool类型
 * */
   let flag:boolean;
   flag=false


/**
 * ----------------------------------3.undefined-------------------------------------
 * undefined类型
 * 默认情况下 `null` 和 `undefined` 是所有类型的子类型
 * */
    let u:undefined=undefined
    console.log(u);
    let num2:number=10;
    // num2=null


/**
 * ----------------------------------3.null-------------------------------------
 * null类型
 * 默认情况下 `null` 和 `undefined` 是所有类型的子类型
 * */

    let n:null=null
    console.log(n);
    


/**
 * ----------------------------------4.字面量---------------------------------------
 * 字面量(自定义变量类型)：变量的值必须和自定义变量类型值一致
 * 也可以使用字面量去指定变量的类型，通过字面量可以确定变量的取值范围
 * */ 
    let userSex:"男"|"女"|"人妖"
    userSex="男"
    userSex="女"




/**
 * ----------------------------------5.any ----------------------------------------
 * 任何类型 没有类型校验
 * */ 
    let anyType:any;
    anyType="zbc"
    anyType=100
    anyType=true

    let userScores:number=100;
    anyType=userScores;


/**
 * ----------------------------------6.unknown ------------------------------------
 * 未知类型: 安全的any类型
*/
    let unkn:unknown;
    unkn="hello"
    unkn={}
    unkn={}
    
// 安全的any类型
    // userScores = unkn;
    



/**
 * ----------------------------------7.联合类型 | ----------------------------------
 * 通过联合类型将多个类型合并为一个类型
*/
    let userPhone:string|number|boolean
    userPhone=1311111111;
    userPhone="1311111111";
    userPhone=false

   

 


/**
 * -----------------------------------8.void----------------------------------------
 * 表示没有任何类型,常用于没有返回值的函数   区别与js   undefined
 * */ 
    function fn1():void{
        console.log("hello");
        
    }
    console.log(fn1());
    

/**
 * -----------------------------------9.never---------------------------------------
 * 表示用户无法达到的类型
 * 例如never类型是哪些总是会抛出异常或者根本就不会有返回值的函数表达式或者箭头函数表达式的返回值类型（死循环）
 * */ 
    function getError():never{
        throw new Error()
    }
    function fn2():never{
        while(true){}
    }


    
/**
 * -----------------------------------10.object-------------------------------------
 * TS 的对象类型，其实就是描述对象中的 `属性` `方法` 的类型，因为对象是由属性和方法组成的
*/
    let obj1={}
    let obj2:Object
    obj2={}
    obj1=true;
    obj1=false;
    let obj3:{id:number,name:string,sex?:string}
    obj3={id:1000,name:"king"}
    let obj4:{id:number,name:string,sex?:string,[propName:string|symbol]:any}
    obj4={id:1001,name:"tom",sex:"男",hobby:"女",getInfo(){}}
/**
 * -----------------------------------11.array--------------------------------------
 * 数组类型
*/
let arr2=[]

// arr2 = [1,2,3,4]
// arr2 = "hello"
let arr3:number[]=[1,2,3,4]
let arr4:string[]=["he","llo"]
let arr5:(string|number|boolean)[]
arr5=["nba",101,true,10000]
// 以下是通过泛型的方式定义数组类型 <type>:泛型语法
let arr6:Array<string>
let arr7:Array<number>
let arr8:Array<number|string>

// 需要定义一个值是对象类型的数组 [{id:number,name:string},{}....]
let arr9:{id:number,name:string}[]
arr9=[{id:100,name:"queen"}]
let arr10:Array<{id:number,name:string}>
arr10=[{id:101,name:"king"}]


/**
 * -----------------------------------12.tuple(元组|固定长度)------------------------
 * 元组tuple 固定长度的数组
*/
let ar1:[number,string]=[100,"hello"]





/**
 * -----------------------------------13.enum---------------------------------------
 * 枚举类型
 * 枚举成员会被赋值为从 0开始递增的数字，同时也会对枚举值到枚举名进行反向映射：
 * 也可以对枚举类型手动赋值，手动赋值的枚举项会接着上一个枚举项递增
 * 手动赋值的枚举项也可以为小数或负数，此时后续未手动赋值的项的递增步长仍为1：
*/

    // 定义一个表示订单状态的枚举类型
enum orderType{
    "代付款",
    "已付款，待发货",
    "已发货，待收货",
    "已收货，待评价",
    "交易完成"
}
let orderTypeStatus:orderType
orderTypeStatus=orderType.交易完成
console.log("当前用户的订单状态是：",orderTypeStatus);
console.log("枚举：",orderType);
enum scoreType{
    "不及格"=59.9,
    "合格",
    "良好"=80,
    "优秀",
    "学神"
}
let studentScoreType:scoreType
let studentScoreType2:scoreType
studentScoreType=scoreType.合格
studentScoreType2=scoreType.优秀
console.log(studentScoreType);
console.log(studentScoreType2);

/**
 * -----------------------------------14.类型别名------------------------------------
 * type 当同一类型（复杂）被多次使用时，可以通过类型别名，简化该类型的使用
 * */ 
// let obj1: {id:string,age:number}
// let obj2: {id:string,work:string}
// let obj3: { id: string, info: {} }
// 对象类型复用
// let obj44: { id: string, [propName: string | symbol]: any }
// let obj55: { id: string, age?: number, work?: string, info?: {} }
// obj55 = { id: '12', age: 20 }

type objType = { id: string, [propName: string | symbol]: any }
    let obj11:objType = {id:'1000',age:18}
    let obj22:objType = {id:'1001',work:"students"}
    // let obj33:objType = {work:"students"}

    type sTY = string

    let str1:sTY = "hello"

    type numType = number

    let num3:numType = 100;

// 设置联合类型




/**
 * ------------------------------------15.交叉类型 &----------------------------------
 * 通过 & 运算符可以将现有的多种类型叠加到一起成为一种类型，它包含了所需的所有类型的特性
 * 注意
 * 原始类型、字面量类型、函数类型等原子类型合并成交叉类型，是没有任何用处的，
 * 因为任何类型都不能满足同时属于多种原子类型
 * */ 
type oneType = {id:number,name:string}

type twoType = {age:number,hobby:string} & oneType

let userInfo:twoType = {id:1000,name:"king",age:18,hobby:"swimming"}

    // 以下类型合并是无效的

    // type type1 = string
    // type type2 = number & type1

    // let telPhon:type2 = 13111111111;


/**
 * -----------------------------------16.函数----------------------------------------
 * */ 
// 1.直接定义
// 2.使用类型别名
// 3.接口定义函数类型





/**
 * -----------------------------------17.接口----------------------------------------
 * */ 
// 1.约束对象内容
// 2.接口继承
// 3.class实现
// 4.接口定义函数类型


/**
 * ------------------------------------18.泛型-----------------------------------------
 * */ 
// 1.定义函数
// 2.使用泛型定义多个参数函数



// 2.泛型约束
// 3.定义泛型接口
// 4.定义泛型类


/**
 * -------------------------------------19.类型别名VS接口------------------------------
 * */ 
// 1.类型别名可以定义丰富的类型
// 2.重复定义（类型别名不能重新开放，接口是可扩展的。）
// 3.扩展性（扩展方法不同 type使用 & 实现继承扩展效果 接口使用extends）



 


  // 类型推断:没有明确的指定类型的时候推测出一个类型
  // 有下面2种情况:
  // 1. 定义变量时赋值了, 推断为对应的类型.
  // 2. 定义变量时没有赋值, 推断为any类型

 

















